#include "unixhead.h"

#include <string>
#include <iostream>
using std::cout;
using std::endl;
using std::string;

class HttpServer
{
public:
    HttpServer(const char * ip, unsigned short port)
    : _ip(ip)
    , _port(port)
    , _listenfd(-1)
    {}

    //RAII
    ~HttpServer() {
        if(_listenfd > 0) {
            close(_listenfd);
        }
    }

    void Start(){
        _listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if(_listenfd < 0) {
            perror("socket");
            return;
        }

        struct sockaddr_in serveraddr;
        memset(&serveraddr, 0, sizeof(serveraddr));
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(_port);
        serveraddr.sin_addr.s_addr = inet_addr(_ip.c_str());

        int reuse = 1;
        if(setsockopt(_listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0){
            perror("setsockopt");
            return;
        }

        if(::bind(_listenfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) {
            perror("bind");
            return;
        }

        if(::listen(_listenfd, 128) < 0) {
            perror("listen");
            return;
        }
    }

    void RecvAndShow() {
        while(1) {
            int netfd = ::accept(_listenfd, nullptr, nullptr);
            if(netfd > 0) {
                char buff[1024] = {0};
                int ret = recv(netfd, buff, sizeof(buff), 0);
                printf("recv %d bytes.\n", ret);
                printf("%s\n", buff);
                //在这里要拼凑一个响应报文
                string msg = Response();
                cout << "msg.length:" << msg.length() << endl;
                //内核发送缓冲区大于msg.size()
                ret = send(netfd, msg.c_str(), msg.size(), 0);
                if(ret == msg.size()) {
                    printf("msg send over\n");
                }
            }
            close(netfd);
            printf("\n\n");
        }
    }

private:
    string Response()
    {
        string firstLine("HTTP/1.1 200 OK\r\n");
        string headers("Content-Type:text/html\r\n");
        string body("<html><body>hello,http</body></html>");
        headers.append("Content-length:")
               .append(std::to_string(body.size()))
               .append("\r\n");
        string emptyLine("\r\n");
        string msg = firstLine + headers + emptyLine + body;
        return msg;
    }

private:
    string _ip;
    unsigned short _port;
    int _listenfd;
};


void test0()
{
    HttpServer server("0.0.0.0", 1280);
    server.Start();
    server.RecvAndShow();
}


int main()
{
    test0();
    return 0;
}
